//
//  ADInputIntercepter.m
//  ADKitDemo
//
//  Created by adu on 2019/1/3.
//  Copyright © 2019 Fission. All rights reserved.
//

#import "ADInputIntercepter.h"
#import "ADKitHeaders.h"

@implementation UIView (InputIntercepter)

- (void)setIntercepter:(ADInputIntercepter *)intercepter {
    objc_setAssociatedObject(self, @selector(intercepter), intercepter, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (ADInputIntercepter *)intercepter {
    return objc_getAssociatedObject(self, @selector(intercepter));
}

@end

@interface ADInputIntercepter ()

@property (nonatomic, weak) UIView *inputView;
@property (nonatomic, copy) NSString *previousText;

@end

@implementation ADInputIntercepter

+ (instancetype)intercepterWithInputView:(UIView *)inputView {
    ADInputIntercepter *intercepter = [[ADInputIntercepter alloc] init];
    intercepter.inputView = inputView;
    if ([inputView isKindOfClass:UITextField.class]) {
        inputView.intercepter = intercepter;
        [[NSNotificationCenter defaultCenter] addObserver:intercepter
                                                 selector:@selector(textInputDidChangeNotification:)
                                                     name:UITextFieldTextDidChangeNotification
                                                   object:inputView];
    }
    if ([inputView isKindOfClass:UITextView.class]) {
        inputView.intercepter = intercepter;
        [[NSNotificationCenter defaultCenter] addObserver:intercepter
                                                 selector:@selector(textInputDidChangeNotification:)
                                                     name:UITextViewTextDidChangeNotification
                                                   object:inputView];
    }
    return intercepter;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _allowType = ADIntercepterAllowAll;
        _decimalPlaces = 2;
        _sepicalString = @"[~`!@#$%^&*()_+-=[]|{};':\",./<>?]{,}/";
    }
    return self;
}

- (void)textInputDidChangeNotification:(NSNotification *)noti {
    if (![noti.object isEqual:self.inputView]) {
        return;
    }
    if (![((UIView *)noti.object) isFirstResponder]) {
        return;
    }
    
    if ([noti.name isEqualToString:UITextFieldTextDidChangeNotification]) {
        [self textFieldDidChangeNotification:noti];
    } else if ([noti.name isEqualToString:UITextViewTextDidChangeNotification]) {
        [self textViewDidChangeNotification:noti];
    }
}

- (void)textFieldDidChangeNotification:(NSNotification *)noti {
    UITextField *textField = (UITextField *)noti.object;
    NSString *inputText = textField.text;
    NSString *primaryLanguage = [textField.textInputMode primaryLanguage];
    UITextRange *selectedRange = [textField markedTextRange];
    UITextPosition *textPosition = [textField positionFromPosition:selectedRange.start
                                                            offset:0];
    
    if ([_previousText isEqualToString:inputText]) {
        return;
    }
    
    inputText = [self processWithText:inputText previousText:self.previousText primaryLanguage:primaryLanguage textPosition:textPosition];
    [textField setValue:inputText forKey:@"text"];
    
    _previousText = textField.text;
}

- (void)textViewDidChangeNotification:(NSNotification *)noti {
    UITextView *textView = (UITextView *)noti.object;
    NSString *inputText = textView.text;
    NSString *primaryLanguage = [textView.textInputMode primaryLanguage];
    UITextRange *selectedRange = [textView markedTextRange];
    UITextPosition *textPosition = [textView positionFromPosition:selectedRange.start
                                                           offset:0];
    
    if ([_previousText isEqualToString:inputText]) {
        return;
    }
    
    inputText = [self processWithText:inputText previousText:self.previousText primaryLanguage:primaryLanguage textPosition:textPosition];
    [textView setValue:inputText forKey:@"text"];
    
    _previousText = textView.text;
}

- (NSString *)processWithText:(NSString *)inputText
                 previousText:(NSString *)previousText
              primaryLanguage:(NSString *)language
                 textPosition:(UITextPosition *)textPosition {
    NSString *string = [self _typeProcessWithText:inputText previousText:previousText primaryLanguage:language textPosition:textPosition];
    string = [self _lengthProcessWithText:string previousText:previousText primaryLanguage:language textPosition:textPosition];
    return string;
}

- (NSString *)_typeProcessWithText:(NSString *)inputText
                      previousText:(NSString *)previousText
                   primaryLanguage:(NSString *)language
                      textPosition:(UITextPosition *)textPosition {
    if (previousText.length >= inputText.length) {
        return inputText;
    }
    
    if (self.regularStr.length > 0) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", self.regularStr];
        return [predicate evaluateWithObject:inputText] ? inputText : previousText;
    }
    
    if (self.allowType & ADIntercepterAllowAll) {
        return inputText;
    }
    
    NSString *inputString = [inputText substringWithRange:NSMakeRange(previousText.length, (inputText.length - previousText.length))];
    if (self.allowType & ADIntercepterAllowDecimal) {
        if ([inputString isEqualToString:@" "]) {
            if (self.typeInterceptBlock) {
                self.typeInterceptBlock(self, inputString);
            }
            return previousText;
        }
        if (![inputText stringByReplacingOccurrencesOfString:@"." withString:@""].ad_isAllNumbers) {
            if (self.typeInterceptBlock) {
                self.typeInterceptBlock(self, inputString);
            }
            return previousText;
        }
        if ([self.previousText rangeOfString:@"."].location != NSNotFound) {
            if ([inputString rangeOfString:@"."].location != NSNotFound) {
                if (self.typeInterceptBlock) {
                    self.typeInterceptBlock(self, inputString);
                }
                return previousText;
            }
        }
        if (self.decimalPlaces > 0) {
            if ([inputText rangeOfString:@"."].location != NSNotFound) {
                NSString *decimal = [inputText componentsSeparatedByString:@"."][1];
                if (decimal.length > self.decimalPlaces) {
                    if (self.typeInterceptBlock) {
                        self.typeInterceptBlock(self, inputString);
                    }
                    return previousText;
                }
            }
        }
        return inputText;
    }
    if (!(self.allowType & ADIntercepterAllowNumber)) {
        if (inputString.ad_isAllNumbers) {
            if (self.typeInterceptBlock) {
                self.typeInterceptBlock(self, inputString);
            }
            return previousText;
        }
    }
    if (!(self.allowType & ADIntercepterAllowLetter)) {
        if (inputString.ad_isAllCharacter) {
            if (self.typeInterceptBlock) {
                self.typeInterceptBlock(self, inputString);
            }
            return previousText;
        }
    }
    if (!(self.allowType & ADIntercepterAllowChinese)) {
        if (inputString.ad_haveChinese) {
            if (self.typeInterceptBlock) {
                self.typeInterceptBlock(self, inputString);
            }
            return previousText;
        }
    }
    if (!(self.allowType & ADIntercepterAllowEmoji)) {
        if (inputString.ad_haveEmoji) {
            if (self.typeInterceptBlock) {
                self.typeInterceptBlock(self, inputString);
            }
            return previousText;
        }
    }
    if (!(self.allowType & ADIntercepterAllowSepical)) {
        if ([self haveSpecialString:inputString]) {
            if (self.typeInterceptBlock) {
                self.typeInterceptBlock(self, inputString);
            }
            return previousText;
        }
    }
    return inputText;
}

- (NSString *)_lengthProcessWithText:(NSString *)inputText
                        previousText:(NSString *)previousText
                     primaryLanguage:(NSString *)language
                        textPosition:(UITextPosition *)textPosition {
    if ([language isEqualToString:@"zh-Hans"] || [language isEqualToString:@"zh-Hant"]) { // 简繁体中文输入
        if (textPosition) {
            return inputText;
        }
    }
    if (self.allowType & ADIntercepterAllowDecimal) {
        NSString *inputString = [inputText substringWithRange:NSMakeRange(previousText.length, (inputText.length - previousText.length))];
        if (inputText.length < self.minLength) {
            if (self.lengthInterceptBlock) {
                self.lengthInterceptBlock(self, inputText);
            }
        }
        if (inputText.length == self.maxLength && [inputString isEqualToString:@"."]) {
            return _previousText;
        }
    }
    if (self.doubleByteMode) {
        NSUInteger textBytesLength = [inputText lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
        if (textBytesLength < self.minLength) {
            if (self.lengthInterceptBlock) {
                self.lengthInterceptBlock(self, inputText);
            }
        }
        if (textBytesLength > self.maxLength) {
            NSRange range;
            NSUInteger byteLength = 0;
            for(int i = 0; i < inputText.length; i += range.length) {
                range = [inputText rangeOfComposedCharacterSequenceAtIndex:i];
                byteLength += strlen([[inputText substringWithRange:range] UTF8String]);
                if (byteLength > self.maxLength) {
                    if (self.lengthInterceptBlock) {
                        self.lengthInterceptBlock(self, inputText);
                    }
                    return [inputText substringWithRange:NSMakeRange(0, range.location)];
                }
            }
        }
    }else{
        if (inputText.length < self.minLength) {
            if (self.lengthInterceptBlock) {
                self.lengthInterceptBlock(self, inputText);
            }
        }
        if (inputText.length > self.maxLength) {
            NSRange range = [inputText rangeOfComposedCharacterSequenceAtIndex:self.maxLength];
            if (range.length == 1) {
                if (self.lengthInterceptBlock) {
                    self.lengthInterceptBlock(self, inputText);
                }
                return [inputText substringToIndex:self.maxLength];
            } else {
                range = [inputText rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, self.maxLength)];
                if (self.lengthInterceptBlock) {
                    self.lengthInterceptBlock(self, inputText);
                }
                return [inputText substringWithRange:range];
            }
        }
    }
    return inputText;
}

- (BOOL)haveSpecialString:(NSString *)string {
    for (int i = 0; i < string.length; i++) {
        NSString *subStr = [string substringWithRange:NSMakeRange(i, 1)];
        if ([_sepicalString rangeOfString:subStr].location != NSNotFound) {
            return YES;
        }
    }
    return NO;
}

@end
